#include "core/CAutoMutexLocker.h"
#include "common/common.h"
#include "core/TCFixedString.h"
#include "string/stringoutput.h"
#include "testlibpilo.h"


static INT32 case_CAutoMutexLocker_useCthreadMutex(void* param);


static case_testing_t g_cases_CThreadMutex[] = {
    {1,  "with CthreadMutex                                 ", 0,  case_CAutoMutexLocker_useCthreadMutex,           -1},
};

static INT32 g_id = 0;

INT32 test_CAutoMutexLocker_Functional(INT32 id, BOOL breakOnErrorOccured)
{
    g_id = id;

    FormatOutputToConsole("Testing Part_%d <cautomutexlocker.h>\n", id);
    int i=0;
    for (i=0; i<MCF_COUNT_OF(g_cases_CThreadMutex); i++) {
        case_testing_t * caseParam = &g_cases_CThreadMutex[i];
        ASSERT(caseParam != NULL);
        FormatOutputToConsole(" #[%03d.%03d]: Testing %s",g_id, caseParam->ct_id, caseParam->ct_decription);

        caseParam->ct_result = caseParam->ct_function(static_cast<case_testing_t *>(caseParam));
        if (caseParam->ct_result == 0) { //ok
            FormatOutputToConsole("[PASSED]\n");
        } else {
            FormatOutputToConsole("[FAILED:%d]\n",caseParam->ct_result);
            if (breakOnErrorOccured) {
                ASSERT(FALSE);
            }
        }
    }

    FormatOutputToConsole("Result of Part_%d <cautomutexlocker.h> total  %d, failed %d\n\n",id, MCF_COUNT_OF(g_cases_CThreadMutex), failedOFCases(g_cases_CThreadMutex,MCF_COUNT_OF(g_cases_CThreadMutex)));
    return 0;
}

static UINT32 glb_testint = 0;

static void _addValue(CThreadMutex* mutex)
{
    CAutoMutexLocker guard(mutex); 
    glb_testint = glb_testint + 5;
}

static THREAD_ROUTINE_RETURN_TYPE THREAD_ROUTINE_CALL runAdd(void* param)
{

    CThreadMutex* mutex = (CThreadMutex*) param;

    int i=0;

    for (i=0; i<20000000; i++) {
        _addValue(mutex);
    }
 

#ifdef WINDOWS
    _endthreadex(0);
#endif 

    return 0;
}

INT32 case_CAutoMutexLocker_useCthreadMutex(void*)
{
    glb_testint = 0;

    CThreadMutex mutex;

#ifdef WINDOWS

    HANDLE  hdl[20];
    int i;
    for( i=0;i<20;++i){
        hdl[i] = (HANDLE) _beginthreadex(0,0, runAdd,(void*) &mutex,0,0);
        if  (hdl[i] == (HANDLE) -1) {
            return -1;
        }
    }

    int rc = WaitForMultipleObjects(20, hdl, TRUE, INFINITE);
    if (rc != WAIT_OBJECT_0)
    {
        return -2;
    }

#else

    pthread_t  tid[20];

    int i;
    for( i=0;i<20;++i){
        if (0 != pthread_create(&tid[i], 0, runAdd,0)) {
            return -1;
        }
    }

    for (i=0; i<20; ++i) {
        pthread_join(tid[i], 0);
    }
#endif

    if (2000000000 != glb_testint) {
        return -3;
    }

    return 0;
}
